{
 "metadata": {
  "name": ""
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "# Translating Python code to Javascript"
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "We have access to a **context**: a dictionary of objects identified by GUIDs, in both Python and Javascript.\n",
      "\n",
      "Each object has methods and attributes. The possible data types for the attributes are:\n",
      "\n",
      "* number (integers, floating point, boolean)\n",
      "* string\n",
      "* array/lists of numbers\n",
      "\n",
      "In addition, we have a set of Python functions that may accept values (simple data types) as arguments. These arguments also have GUIDs (refering to the positional arguments and not values). We want to translate them to Javascript *at runtime*. The translation can be done in Python.\n",
      "\n",
      "This is a difficult problem in general as one would need some sort of Python interpreter in Javascript, or a Python to Javascript compiler. We propose here an alternative solution and is much more limited. We put strict constraints on the problem, which simplifies a lot the translation."
     ]
    },
    {
     "cell_type": "markdown",
     "metadata": {},
     "source": [
      "Specifically, we assume that:\n",
      "\n",
      "* The functions have access to the context through the GUIDs, which are completely determined at initialization time. They also access all their fields and methods.\n",
      "* The functions can perform simple arithmetic operations on their arguments.\n",
      "* In effect, the functions can only resort to a small set of instructions. A function can basically call methods of the context's objects. The parameters of these calls are transformations of the function's arguments.\n",
      "* The exact sequence of these calls is completely determined at initialization time, and does not change afterwards.\n",
      "* There is no dynamic control flow or conditional branching, except within the functions of the instruction set."
     ]
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "instructions = []\n",
      "\n",
      "def _show_instructions():\n",
      "    return '\\n'.join('{fun}(*{args})'.format(fun=fun, args=args)\n",
      "                     for (fun, args) in instructions)\n",
      "\n",
      "class Drop(object):\n",
      "    def __init__(self, name=''):\n",
      "        self.name = name\n",
      "    def _op(self, fun, args=()):\n",
      "        instructions.append((fun, args, ))\n",
      "        return self\n",
      "    #def __getattr__(self, fun):\n",
      "    #    return lambda *args: self._op(fun, args)\n",
      "    def __add__(self, b):\n",
      "        self._op('__add__', (b))\n",
      "        return Drop('{0:s} + {1:s}'.format(self.name, b.name))\n",
      "    def __mul__(self, b):\n",
      "        self._op('__mul__', (b))\n",
      "        return Drop('{0:s} * {1:s}'.format(self.name, b.name))\n",
      "    def __repr__(self):\n",
      "        return self.name\n",
      "a = Drop('a')\n",
      "b = Drop('b')\n",
      "print a\n",
      "print b\n",
      "print (a*b)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "a\n",
        "b\n",
        "a * b\n"
       ]
      }
     ],
     "prompt_number": 73
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "import math\n",
      "class InstructionSet(object):\n",
      "    \"\"\"This class implements static methods that are\n",
      "    part of the instruction set of our intermediate \n",
      "    language. These instructions are available in\n",
      "    Python and all backend languages.\"\"\"\n",
      "    @staticmethod\n",
      "    def exp(x):\n",
      "        return math.exp(x)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 44
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def transform(dx, dy, a=1., b=1.):\n",
      "    return (InstructionSet.exp(dx*a+b),\n",
      "            InstructionSet.exp(dy*b+b))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 45
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "transform(.5, 2., b=2.)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 46,
       "text": [
        "(12.182493960703473, 403.4287934927351)"
       ]
      }
     ],
     "prompt_number": 46
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "class UserData(object):\n",
      "    def __init__(self):\n",
      "        self.a = 1.\n",
      "        self.b = 2.\n",
      "ud = UserData()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 47
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "class InstructionSetSpy(object):\n",
      "    def __init__(self, name=''):\n",
      "        self._name = name\n",
      "    def _op(self, fun, args=()):\n",
      "        instructions.append((fun, args, ))\n",
      "        return self\n",
      "    def exp(self, x):\n",
      "        self._op('exp', x)\n",
      "        return self\n",
      "InstructionSet = InstructionSetSpy()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 61
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "dx = Drop('dx')\n",
      "dy = Drop('dy')\n",
      "tx, ty = transform(dx, dy, b=ud.b)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 62
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "print tx._show_spy()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "exp(*dx)\n",
        "exp(*dy)\n"
       ]
      }
     ],
     "prompt_number": 63
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    }
   ],
   "metadata": {}
  }
 ]
}